using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Collections.ObjectModel;


namespace Perovich.GameObjects.ThreeDimensional
{
    /// <summary>
    /// Provides data for the <see cref="ModelObject3Dbase.CameraAdded"/> event.
    /// </summary>
    public class CameraAddedEventArgs : EventArgs
    {
        private Camera addedCamera;

        /// <summary>
        /// Gets the <see cref="Camera"/> that was added to the <see cref="ModelObject3Dbase"/>.
        /// </summary>
        public Camera AddedCamera
        {
            get { return addedCamera; }
        }
        /// <summary>
        /// Constructs a new instance of the <see cref="CameraAddedEventArgs"/> with the specified <see cref="Camera"/>
        /// </summary>
        /// <param name="camera">The <see cref="Camera"/> that was added.</param>
        public CameraAddedEventArgs(Camera camera)
        {
            addedCamera = camera;
        }
    }

    /// <summary>
    /// The <see cref="ModelObject3Dbase"/> class is an abstract base class implementing everything common to objects in three dimensions drawn with a <see cref="Model"/>.
    /// </summary>
    public abstract class ModelObject3Dbase : DrawableObject3D
    {
        private Model _model;
        private Vector3 _origin;
        List<Camera> _cameras = new List<Camera>();
        ReadOnlyCollection<Camera> collection;

        /// <summary>
        /// Gets the collection of <see cref="Camera"/>s this <see cref="ModelObject3Dbase"/> is drawn in.
        /// </summary>
        protected ReadOnlyCollection<Camera> Cameras
        {
            get
            {
                return collection;
            }
        }

        /// <summary>
        /// Adds one or more <see cref="Camera"/>s to the <see cref="ModelObject3Dbase.Cameras"/> collection.
        /// </summary>
        /// <param name="cameras">The <see cref="Camera"/>s to add.</param>
        public void AddCameras(params Camera[] cameras)
        {
            if (cameras == null)
                throw new ArgumentNullException("cameras");
            foreach (Camera cam in cameras)
            {
                _cameras.Add(cam);
                SignalCameraAdded(cam);
            }
        }

        /// <summary>
        /// Triggered when a <see cref="Camera"/> is added to the <see cref="ModelObject3Dbase.Cameras"/> collection.
        /// </summary>
        protected event EventHandler<CameraAddedEventArgs> CameraAdded;


        /// <summary>
        /// Triggered when the <see cref="ModelObject3Dbase.ObjectModel"/> property is changed.
        /// </summary>
        protected event EventHandler ModelChanged;

        void SignalModelChanged()
        {
            if (ModelChanged != null)
            {
                ModelChanged(this, new EventArgs());
            }
        }

        void SignalCameraAdded(Camera c)
        {
            if (CameraAdded != null)
            {
                CameraAdded(this, new CameraAddedEventArgs(c));
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="Model"/> used to draw this <see cref="ModelObject3Dbase"/>.
        /// </summary>
        public Model ObjectModel
        {
            get
            {
                return _model;
            }
            set
            {
                _model = value;
                SignalModelChanged();
            }
        }


        /// <summary>
        /// Gets or sets the origin of the <see cref="ModelObject3Dbase"/>.
        /// </summary>
        public Vector3 Origin
        {
            get { return _origin; }
            set { _origin = value; }
        }


        /// <summary>
        /// constructs a new instance of the <see cref="ModelObject3Dbase"/> class.
        /// </summary>
        /// <param name="game"></param>
        protected ModelObject3Dbase(Interfaces.ICanHoldComponents game)
            : base(game)
        {
            collection = new ReadOnlyCollection<Camera>(_cameras);
            _model = null;
        }
        
    }
}
